package com.zw.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.github.pagehelper.util.StringUtil;
import com.zw.config.context.AuthenticationContextHolder;
import com.zw.dto.RegisterDto;
import com.zw.dto.SaveUserDto;
import com.zw.dto.UserListDto;
import com.zw.entity.SysRole;
import com.zw.entity.SysUser;
import com.zw.entity.SysUserRole;
import com.zw.mapper.SysMenuMapper;
import com.zw.mapper.SysRoleMapper;
import com.zw.mapper.SysUserMapper;
import com.zw.mapper.SysUserRoleMapper;
import com.zw.service.SysUserService;
import com.zw.utils.*;
import com.zw.utils.UUID;
import com.zw.vo.LoginUser;
import com.zw.vo.LoginVO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.ResponseEntity;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.*;
import java.util.concurrent.ThreadLocalRandom;
import java.util.concurrent.atomic.AtomicReference;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * 用户信息表(SysUser)表服务实现类
 *
 * @author makejava
 * @since 2025-01-02 16:54:54
 */
@Service
@Slf4j
public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> implements SysUserService {
    @Resource
    private AuthenticationManager authenticationManager;
    @Resource
    private TokenUtils tokenUtils;
    @Resource
    private SysMenuMapper sysMenuMapper;

    @Resource
    private SysRoleMapper sysRoleMapper;
    @Resource
    private SysUserMapper sysUserMapper;
    @Resource
    private SysUserRoleMapper sysUserRoleMapper;

    @Override
    public LoginVO login(String email, String password) {
        LoginVO loginVO = new LoginVO();
        UsernamePasswordAuthenticationToken authToken = new UsernamePasswordAuthenticationToken(email, password);
        AuthenticationContextHolder.setContext(authToken);
        // 使用authenticationManager调用loadUserByUsername获取数据库中的用户信息,
        Authentication authentication = authenticationManager.authenticate(authToken);
        if (authentication == null) {
            throw new RuntimeException("登录失败");
        }
        LoginUser loginUser = (LoginUser) authentication.getPrincipal();
        String token = tokenUtils.createToken(loginUser);
        loginVO.setToken(token);
        loginVO.setPermissions(loginUser.getPermissions());
        return loginVO;
    }

    @Override
    public void validate(SysUser user) {
        Authentication usernamePasswordAuthenticationToken = AuthenticationContextHolder.getContext();
        //String username = usernamePasswordAuthenticationToken.getName();
        String password = usernamePasswordAuthenticationToken.getCredentials().toString();
        //密码不正确抛出相应提示
        String passwordMd5 = Md5Utils.strMd5(Md5Utils.strMd5(password) + user.getMaskNum());
        if (!passwordMd5.equals(user.getPassword())) {
            throw new RuntimeException("用户密码错误，登录失败！");
        }
        user.setPassword(password);
    }

    @Override
    public Set<String> getMenuPermission(SysUser user) {
        Set<String> perms = new HashSet<String>();
        List<SysRole> roles = sysRoleMapper.selectRolesByUserId(user.getUserId());
        if (!roles.isEmpty()) {
            // 多角色设置permissions属性，以便数据权限匹配权限
            for (SysRole role : roles) {
                Set<String> rolePerms = sysMenuMapper.selectMenuPermsByRoleId(role.getRoleId());
                perms.addAll(rolePerms);
            }
        } else {
            perms.addAll(sysMenuMapper.selectMenuPermsByUserId(user.getUserId()));
        }
        return perms;
    }

    /**
     * 查询用户列表
     *
     * @param dto
     * @return
     */
    @Override
    public ResponseEntity<PageInfo<SysUser>> queryAllUsers(UserListDto dto) {
        List<SysUser> list = new ArrayList<>();
        String role = SecurityUtils.getRole();
        if ("admin".equals(role)) {
            //超管可以查询所有的用户信息，并且可以操作
            PageHelper.startPage(dto.getPageNum(), dto.getPageSize());
            List<SysUser> users = sysUserMapper.selectList(new QueryWrapper<SysUser>()
                    .ne("del_flag", 2)
                    .eq(StringUtil.isNotEmpty(dto.getStatus()), "status", dto.getStatus())
                    .like(StringUtil.isNotEmpty(dto.getUserName()), "user_name", dto.getUserName())
                    .eq(StringUtil.isNotEmpty(dto.getPhonenumber()), "phonenumber", dto.getPhonenumber()));
            list = CopyUtils.copyList(users, SysUser.class);
        } else {
            //只能查看自己的信息，且不能操作，例如修改删除等
            SysUser sysUser = sysUserMapper.selectById(SecurityUtils.getUserId());
            list.add(sysUser);
        }
        return ResponseEntity.ok(new PageInfo<>(list));
    }

    @Override
    public String getRoleKeyByUserId(Long userId) {
        String roleKey = null;
        SysUserRole userRole = sysUserRoleMapper.selectOne(new QueryWrapper<SysUserRole>().eq("user_id", userId));
        if (Objects.nonNull(userRole)) {
            SysRole sysRole = sysRoleMapper.selectById(userRole.getRoleId());
            if (Objects.nonNull(sysRole)) {
                roleKey = sysRole.getRoleKey();
            }
        }
        return roleKey;
    }

    /**
     * 新增、编辑用户
     *
     * @param dto
     * @return
     */
    @Override
    public Boolean saveOrUpdateUser(SaveUserDto dto) {
        int result = 0;
        List<SysUser> list = sysUserMapper.selectList(new QueryWrapper<SysUser>().eq("del_flag", 0));
        List<String> stringStream = list.stream().map(SysUser::getMaskNum).collect(Collectors.toList());
        OptionalInt max = stringStream.stream()
                .mapToInt(Integer::parseInt) // 将String转换为int
                .max(); // 找到最大值

        if (Objects.nonNull(dto)) {
            if (StringUtil.isNotEmpty(dto.getUserId())) {
                //修改用户信息
                SysUser sysUser = CopyUtils.copyObj(dto, SysUser.class);
                result = this.sysUserMapper.update(sysUser, new QueryWrapper<SysUser>().eq("user_id", dto.getUserId()));
            } else {
                //新增用户
                SysUser sysUser = CopyUtils.copyObj(dto, SysUser.class);
                long userId = UUID.getSecureRandom().nextLong();
                sysUser.setUserId(userId);
                sysUser.setMaskNum(max.getAsInt() + 1 + "");
                sysUser.setPassword(Md5Utils.strMd5(Md5Utils.strMd5(dto.getPassword()) + sysUser.getMaskNum()));
                result = this.sysUserMapper.insert(sysUser);
            }
        }
        if (result > 0) {
            return true;
        }
        return false;
    }

    /**
     * 用户注册
     * 注意：默认授予普通用户角色
     *
     * @param registerDto
     * @return
     */
    @Override
    public Boolean register(RegisterDto registerDto) {
        if (Objects.isNull(registerDto)) {
            throw new RuntimeException("请求参数错误！");
        }
        //首先应该查询是否已经存在该用户
        SysUser queryUser = sysUserMapper.selectOne(new QueryWrapper<SysUser>().lambda()
                .eq(SysUser::getEmail, registerDto.getEmail())
                .eq(SysUser::getDelFlag, 0));
        if (Objects.nonNull(queryUser)) {
            throw new RuntimeException("该邮箱用户已存在，请勿重复注册！");
        }
        SysUser sysUser = CopyUtils.copyObj(registerDto, SysUser.class);
        long userId = IdUtils.getId();
        sysUser.setUserId(userId);
        int maskNum = generateRandomNumber();
        sysUser.setMaskNum(String.valueOf(maskNum));
        sysUser.setCreateTime(new Date());
        sysUser.setPassword(Md5Utils.strMd5(Md5Utils.strMd5(registerDto.getPassword()) + maskNum));
        int insertUser = this.sysUserMapper.insert(sysUser);
        int insertRole = 0;
        if (insertUser > 0) {
            log.info("用户：{},新增成功，即将开始添加角色绑定信息！", registerDto.getEmail());
            //授予普通用户角色
            SysUserRole sysUserRole = new SysUserRole();
            sysUserRole.setUserId(userId);
            sysUserRole.setRoleId(2L);
            insertRole = sysUserRoleMapper.insertOne(sysUserRole);
        }
        if (insertUser > 0 && insertRole > 0) {
            log.info("用户：{},注册成功！", registerDto.getEmail());
            return true;
        }
        return false;
    }

    /**
     * 生成4-6位随机整数，4/5/6位出现概率相等
     *
     * @return 随机数字，范围：1000 ~ 999999
     */
    public static int generateRandomNumber() {
        // 随机选择位数：4、5、6
        int length = ThreadLocalRandom.current().nextInt(4, 7);
        // 计算范围边界
        int min = (int) Math.pow(10, length - 1);
        int max = (int) Math.pow(10, length) - 1;
        // 生成并返回随机数
        return ThreadLocalRandom.current().nextInt(min, max + 1);
    }
}
